home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_09_02
/
9n02058a
< prev
next >
Wrap
Text File
|
1990-12-22
|
25KB
|
595 lines
/***********************************************************
* Node-Positioning for General Trees, by John Q. Walker II
*
* Initiated by calling procedure TreePosition().
**********************************************************/
#include <stdlib.h>
/*----------------------------------------------------------
* Implementation dependent: Set the values for each of
* these variables.
*--------------------------------------------------------*/
#define NODE_WIDTH 20 /* Width of a node? */
#define NODE_HEIGHT 10 /* Height of a node? */
#define FRAME_THICKNESS 1 /* Fixed-sized node frame?*/
#define SUBTREE_SEPARATION 5 /* Gap between subtrees? */
#define SIBLING_SEPARATION 4 /* Gap between siblings? */
#define LEVEL_SEPARATION 5 /* Gap between levels? */
#define MAXIMUM_DEPTH 10 /* Biggest tree? */
/*----------------------------------------------------------
* Implementation dependent: The structure for one node
* - The first 4 pointers must be set for each node before
* this algorithm is called.
* - The X and Y coordinates must be set for only the apex
* of the tree upon entry; they will be set by this
* algorithm for all the other nodes.
* - The next three elements are used only for the duration
* of the algorithm.
* - Actual contents of the node depend on your application.
*--------------------------------------------------------*/
typedef int COORD; /* X,Y coordinate type */
typedef struct node {
struct node *parent; /* ptr: node's parent */
struct node *offspring; /* ptr: leftmost child */
struct node *leftsibling; /* ptr: sibling on left */
struct node *rightsibling; /* ptr: sibling on right */
COORD xCoordinate; /* node's current x coord */
COORD yCoordinate; /* node's current y coord */
struct node *prev; /* ptr: lefthand neighbor */
float flPrelim; /* preliminary x coord */
float flModifier; /* temporary modifier */
char info[80]; /* pick your contents! */
} *PNODE; /* ptr: a node structure */
/*----------------------------------------------------------
* Global variables used by the algorithm
*--------------------------------------------------------*/
typedef enum { FALSE, TRUE } BOOL;
typedef enum { FRAME, NO_FRAME } FRAME_TYPE;
typedef enum { NORTH, SOUTH, EAST, WEST } ROOT_ORIENTATION;
typedef struct prev_node { /* one list element */
PNODE pPreviousNode; /* ptr: previous at level */
struct prev_node *pNextLevel; /* ptr: next element */
} *PPREVIOUS_NODE;
static FRAME_TYPE FrameType = FRAME; /* Show a frame */
static ROOT_ORIENTATION RootOrientation = NORTH; /* At top*/
static PPREVIOUS_NODE pLevelZero = (PPREVIOUS_NODE)0;
static COORD xTopAdjustment; /* How to adjust the apex */
static COORD yTopAdjustment; /* How to adjust the apex */
static float flMeanWidth; /* Ave. width of 2 nodes */
#define FIRST_TIME (0) /* recursive proc flag */
/*----------------------------------------------------------
* Implemented as macros, but could be implemented as
* procedures depending on your particular node structures
*--------------------------------------------------------*/
#define FirstChild(node) ((PNODE)((node)->offspring))
#define LeftSibling(node) ((PNODE)((node)->leftsibling))
#define RightSibling(node) ((PNODE)((node)->rightsibling))
#define Parent(node) ((PNODE)((node)->parent))
#define LeftNeighbor(node) ((PNODE)((node)->prev))
#define IsLeaf(node) \
(((node)&&(!((node)->offspring)))?TRUE:FALSE)
#define HasChild(node) \
(((node)&&((node)->offspring))?TRUE:FALSE)
#define HasLeftSibling(node) \
(((node)&&((node)->leftsibling))?TRUE:FALSE)
#define HasRightSibling(node) \
(((node)&&((node)->rightsibling))?TRUE:FALSE)
static PNODE GetPrevNodeAtLevel (unsigned nLevelNbr)
{
/*------------------------------------------------------
* List Manipulation: Return pointer to previous node at
* this level
*----------------------------------------------------*/
PPREVIOUS_NODE pTempNode; /* used in the for-loop */
unsigned i = 0; /* level counter */
for (pTempNode = pLevelZero; (pTempNode);
pTempNode = pTempNode->pNextLevel) {
if (i++ == nLevelNbr)
/* Reached desired level. Return its pointer */
return (pTempNode->pPreviousNode);
}
return ((PNODE)0); /* No pointer yet for this level. */
}
static BOOL SetPrevNodeAtLevel (unsigned nLevelNbr,
PNODE pThisNode)
{
/*------------------------------------------------------
* List Manipulation: Set the list element to the
* previous node at this level
*----------------------------------------------------*/
PPREVIOUS_NODE pTempNode; /* used in the for-loop */
PPREVIOUS_NODE pNewNode; /* newly-allocated memory */
unsigned i = 0; /* level counter */
for (pTempNode = pLevelZero; (pTempNode);
pTempNode = pTempNode->pNextLevel) {
if (i++ == nLevelNbr) {
/* Reached desired level. Return its pointer */
pTempNode->pPreviousNode = pThisNode;
return (TRUE);
}
else if (pTempNode->pNextLevel==(PPREVIOUS_NODE)0) {
/* Looks like we need a new level: add it. */
/* We need to keep going--should be the next. */
pNewNode = (PPREVIOUS_NODE)
malloc(sizeof(struct prev_node));
if (pNewNode) {
pNewNode->pPreviousNode = (PNODE)0;
pNewNode->pNextLevel = (PPREVIOUS_NODE)0;
pTempNode->pNextLevel = pNewNode;
}
else return (FALSE); /* The malloc failed. */
}
}
/* Should only get here if pLevelZero is 0. */
pLevelZero = (PPREVIOUS_NODE)
malloc(sizeof(struct prev_node));
if (pLevelZero) {
pLevelZero->pPreviousNode = pThisNode;
pLevelZero->pNextLevel = (PPREVIOUS_NODE)0;
return (TRUE);
}
else return (FALSE); /* The malloc() failed. */
}
static void InitPrevNodeAtLevel (void)
{
/*------------------------------------------------------
* List Manipulation: Initialize the list of the
* previous node at each level to all zeros.
*----------------------------------------------------*/
PPREVIOUS_NODE pTempNode = pLevelZero; /* the start */
for ( ; (pTempNode); pTempNode = pTempNode->pNextLevel)
pTempNode->pPreviousNode = (PNODE)0;
}
static BOOL CheckExtentsRange(long lxTemp, long lyTemp)
{
/*------------------------------------------------------
* Insert your own code here, to check when the
* tree drawing is going to be too big. My region is no
* more that 64000 units square.
*----------------------------------------------------*/
if ((labs(lxTemp) > 32000) || (labs(lyTemp) > 32000))
return (FALSE);
else
return (TRUE);
}
static void TreeMeanNodeSize (PNODE pLeftNode,
PNODE pRightNode)
{
/*------------------------------------------------------
* Write your own code for this procedure if your
* rendered nodes will have variable sizes.
*------------------------------------------------------
* Here I add the width of the contents of the
* right half of the pLeftNode to the left half of the
* right node. Since the size of the contents for all
* nodes is currently the same, this module computes the
* following trivial computation.
*----------------------------------------------------*/
flMeanWidth = (float)0.0; /* Initialize this global